package com.gxks.lhs.security;

import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
public class JwtTokenProvider {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //改到配置中
    private static String secretKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    private final long accesssExpiresIn = 1800000; // 30min
    private final long refreshExpiresIn = 2592000000L;//3day


    /**
     * 生成token
     *
     * @param userId 用户名
     * @param roles  角色
     * @return token
     */
    public String generateAccessToken(String userId, String roles) {
        Claims claims = Jwts.claims().setSubject(userId);
//        claims.put("userId",userId)
        claims.put("roles", roles);
        Date now = new Date();
        Date validity = new Date(now.getTime() + accesssExpiresIn);
        String accessToken = Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(validity)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        stringRedisTemplate.opsForValue().set("access_token:" + roles + ":" + userId, accessToken, 30, TimeUnit.MINUTES); // 设置过期时间与Access Token一致
        return accessToken;
    }

    public String generateRefreshToken(String userId, String roles) {
        // 创建令牌的声明和有效期
        Claims claims = Jwts.claims().setSubject(userId);
        claims.put("roles", roles);
        Date now = new Date();
        Date validity = new Date(now.getTime() + refreshExpiresIn);
        String refreshToken = Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(validity)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        stringRedisTemplate.opsForValue().set("refresh_token:" + roles + ":" + userId, refreshToken, 3, TimeUnit.DAYS);
        // 构建刷新令牌
        return refreshToken;
    }

    /**
     * 根据token获取Authentication对象
     *
     * @param token JWT token
     * @return Authentication对象
     */
    public Authentication getAuthenticationFromAccessToken(String token) {
        // 解析JWT token获取claims
        Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
        System.out.println("userId from JWT: " + claims.getSubject());
        System.out.println(claims);
        // 根据claims创建UserDetails对象
        UserDetails userDetails = User.builder()
                .username(claims.getSubject())  // 设置username
                .password("")  // 设置password为 ""
                .roles(claims.get("roles", String.class))  // 设置roles
                .build();

        // 创建带有空密码的UsernamePasswordAuthenticationToken对象
        return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
    }

    /**
     * 验证令牌是否有效
     *
     * @param token 传入的令牌
     * @return 如果令牌有效则返回true，否则返回false
     */
    public boolean validateAccessToken(String token) {
        try {
            // 使用指定的密钥解析令牌并获取声明
            Claims claims = parseToken(token);
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            // 判断声明中的过期时间是否在当前时间之后
            return !claimsJws.getBody().getExpiration().before(new Date());
//           根据redis判断token是否有效
//            return stringRedisTemplate.opsForValue().get(claims.get("roles", String.class)+":" + claims.getSubject() + ":access_token") != null;
        } catch (Exception e) {
            // 如果出现异常，表示令牌无效
            return false;
        }
    }

    public boolean validateRefreshToken(String refreshToken) {
        try {
            // 使用指定的密钥解析令牌并获取声明
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(refreshToken);
            // 判断声明中的过期时间是否在当前时间之后
            return !claimsJws.getBody().getExpiration().before(new Date());
        } catch (Exception e) {
            // 如果出现异常，表示令牌无效
            return false;
        }
    }

    // 此方法用于解析 JWT 并获取其中的声明信息
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token)
                .getBody();
    }


    public static String getUserIdFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.getSubject(); // 用户ID存储在 JWT 的 subject 中
    }

    public static String getUsernameFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.getSubject(); // 假设用户名存储在 JWT 的 "username" 声明中
    }

    public static String getRolesFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.get("roles", String.class); // 假设用户名存储在 JWT 的 "username" 声明中
    }

}
